package com.sitech.ibnms.c3p.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;

import static com.sitech.ibnms.c3p.Application.sneakyThrow;

/**
 * Created by liujhc on 7/21.
 */
public final class JSONUtil {

    private JSONUtil() {
    }

    public static ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 解决全大写属性被转成部分小写的问题
        mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
            @Override
            public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
                return translate(method, defaultName);
            }

            @Override
            public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
                return translate(method, defaultName);
            }

            private String translate(AnnotatedMethod method, String defaultName) {
                String name = method.getName();
                // setXXX getXXX isXXX
                name = name.substring(name.length() - defaultName.length());
                return name.length() == 1 || name.matches(".*[a-z].*") ? defaultName : name;
            }
        });
        return mapper;
    }

    /**
     * 将java对象转换成json字符串
     *
     * @param obj
     * @return
     */
    public static String toJSON(Object obj) {
        try {
            if (obj == null) {
                return null;
            } else {
                return objectMapper().writeValueAsString(obj);
            }
        } catch (Exception ex) {
            throw sneakyThrow(ex);
        }
    }

    /**
     * 将json字符串数组转换成java的List对象，对象转换成java的Map对象
     *
     * @param json
     * @return
     */
    public static Object fromJSON(String json) {
        return fromJSON(json, Object.class);
    }

    /**
     * 将json字符串数组转换成指定类型的对象
     *
     * @param json
     * @param type
     * @return
     */
    public static <T> T fromJSON(String json, Class<T> type) {
        try {
            if (json == null) {
                return null;
            } else {
                return objectMapper().readValue(json, type);
            }
        } catch (Exception ex) {
            throw sneakyThrow(ex);
        }
    }

    /**
     * 将json字符串数组转换成指定类型的对象,支持泛型</br>
     * <p/>
     * <p>Map&lt;String,User&gt; result = JSONUtil.fromJSON(jsonStr, new
     * TypeReference&lt;Map&lt;String,User&gt;&gt;(){ });</p>
     *
     * @param json
     * @param typeReference
     * @return
     */
    public static <T> T fromJSON(String json, JSONUtil.TypeReference<T> typeReference) {
        try {
            if (json == null) {
                return null;
            } else {
                return (T) objectMapper().readValue(json, typeReference);
            }
        } catch (Exception ex) {
            throw sneakyThrow(ex);
        }
    }

    public abstract static class TypeReference<T> extends com.fasterxml.jackson.core.type.TypeReference<T> {
    }
}
